#pragma once

#include "Connection.hpp"

// class IOService
// {
//     func_t _func;

// public:
//     IOService(func_t func)
//         : _func(func)
//     {
//     }

//     void IORecver(Connection *conn)
//     {
//         cout << "recv" << endl;
//     }

//     void IOSender(Connection *conn)
//     {
//         cout << "send" << endl;
//     }

//     void IOExecter(Connection *conn)
//     {
//         cout << "exet" << endl;
//     }
// };

class IOService
{
    func_t _func;

public:
    IOService(func_t func)
        :_func(func)
    {}

    void IORecver(Connection* conn)
    {
        errno = 0;
        while(true)
        {
            char buffer[1024];
            bzero(buffer, sizeof(buffer));

            int n = recv(conn->getfd(), buffer, sizeof(buffer) - 1, 0);
            if(n > 0)
            {
                buffer[n] = 0;
                conn->Appendbuffer(buffer);
            }
            else
            {
                if(errno == EWOULDBLOCK || errno == EAGAIN)
                {
                    Log(Debug, "source accept finish");
                    break;
                }
                else if(errno == EINTR)
                {
                    Log(Debug, "signal interrupt accept");
                    continue;
                }
                else
                {
                    conn->_execter(conn);
                    return;
                }
            }

            _func(conn);
        }
    }

    void IOSender(Connection* conn)
    {
        errno = 0;
        while(true)
        {
            int n = send(conn->getfd(), conn->Getoutbuffer().c_str(), conn->Getoutbuffer().size(), 0);
            if(n > 0)
            {
                conn->Removebuffer(n);
                if(conn->Getoutbuffer().empty()) break; //缓冲区为空
            }
            else
            {
                if(errno == EWOULDBLOCK || errno == EAGAIN)
                {
                    Log(Debug, "wait write buffer");
                    break; //缓冲区不为空
                }
                else if(errno == EINTR)
                {
                    Log(Debug, "signal interrupt send");
                    continue;
                }
                else
                {
                    conn->_execter(conn);
                    return;
                }
            }
        }

        if(!conn->Getoutbuffer().empty())
        {
            //设置对写事件的监听
            conn->_react->set_WriteRead(conn->getfd(), true, true);
        }
        else //当处理完写事件后，要取消对写事件的关心。
        {
           conn->_react->set_WriteRead(conn->getfd(), true, false);
        }
    }

    void IOExecter(Connection* conn)
    {
        errno = 0;
        conn->_react->RemoveConnection(conn->getfd());
    }
};